home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / gfx / show / svoUtah22.lha / svoUtahRLE / source / URT / lib / Runput.c < prev    next >
C/C++ Source or Header  |  1990-08-02  |  11KB  |  385 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * Runput.c - General purpose Run Length Encoding.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    Mon Aug  9 1982
  28.  * Copyright (c) 1982,1986 Spencer W. Thomas
  29.  * 
  30.  * $Id: Runput.c,v 3.0 90/08/03 15:19:58 spencer Exp $
  31.  * 
  32.  * Modified by:    Todd W. Fuqua
  33.  *     Date:    Jul 22 1984
  34.  * convert to new RLE format to make room for larger frame buffers
  35.  */
  36.  
  37. /* THIS IS WAY OUT OF DATE.  See rle.5.
  38.  * The output file format is:
  39.  * 
  40.  * Word 0:    A "magic" number.  The top byte of the word contains
  41.  *        the letter 'R' or the letter 'W'.  'W' indicates that
  42.  *        only black and white information was saved.  The bottom
  43.  *        byte is one of the following:
  44.  *    ' ':    Means a straight "box" save, -S flag was given.
  45.  *    'B':    Image saved with background color, clear screen to
  46.  *        background before restoring image.
  47.  *    'O':    Image saved in overlay mode.
  48.  * 
  49.  * Words 1-6:    The structure
  50.  * {     short   xpos,            Lower left corner
  51.  *             ypos,
  52.  *             xsize,            Size of saved box
  53.  *             ysize;
  54.  *     char    rgb[3];            Background color
  55.  *     char    map;            flag for map presence
  56.  * }
  57.  * 
  58.  * If the map flag is non-zero, then the color map will follow as 
  59.  * 3*256 16 bit words, first the red map, then the green map, and
  60.  * finally the blue map.
  61.  * 
  62.  * Following the setup information is the Run Length Encoded image.
  63.  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
  64.  * possibly one or more following words (all words are 16 bits).  The
  65.  * instruction opcodes are:
  66.  * 
  67.  * SkipLines (1):   The bottom 10 bits are an unsigned number to be added to
  68.  *            current Y position.
  69.  * 
  70.  * SetColor (2):    The datum indicates which color is to be loaded with
  71.  *             the data described by the following ByteData and
  72.  *             RunData instructions.  0->red, 1->green, 2->blue.  The
  73.  *             operation also resets the X position to the initial
  74.  *             X (i.e. a carriage return operation is performed).
  75.  * 
  76.  * SkipPixels (3):  The bottom 10 bits are an unsigned number to be
  77.  *             added to the current X position.
  78.  * 
  79.  * ByteData (5):    The datum is one less than the number of bytes of
  80.  *             color data following.  If the number of bytes is
  81.  *             odd, a filler byte will be appended to the end of
  82.  *             the byte string to make an integral number of 16-bit
  83.  *             words.  The bytes are in PDP-11 order.  The X
  84.  *             position is incremented to follow the last byte of
  85.  *             data.
  86.  * 
  87.  * RunData (6):        The datum is one less than the run length.  The
  88.  *             following word contains (in its lower 8 bits) the
  89.  *             color of the run.  The X position is incremented to
  90.  *             follow the last byte in the run.
  91.  */
  92.  
  93. #include    "stdio.h"
  94. #include    "rle_put.h"
  95. #include    "rle.h"
  96. #include    "rle_code.h"
  97. #ifdef USE_STDLIB_H
  98. #include    <stdlib.h>
  99. #else
  100.  
  101. #ifdef USE_STRING_H
  102. #include    <string.h>
  103. #else
  104. #include    <strings.h>
  105. #endif /* USE_STRING_H */
  106.  
  107. #ifndef VOID_STAR
  108. extern char * malloc();
  109. #else
  110. extern void *malloc();
  111. #endif /* VOID_STAR */
  112. extern void free();
  113.  
  114. #endif /* USE_STDLIB_H */
  115.  
  116. #define UPPER 255            /* anything bigger ain't a byte */
  117.  
  118. /*
  119.  * Macros to make writing instructions with correct byte order easier.
  120.  */
  121. /* Write a two-byte value in little_endian order. */
  122. #define    put16(a)    (putc((a)&0xff,rle_fd),putc(((a)>>8)&0xff,rle_fd))
  123.  
  124. /* short instructions */
  125. #define mk_short_1(oper,a1)        /* one argument short */ \
  126.     putc(oper,rle_fd), putc((char)a1,rle_fd)
  127.  
  128. #define mk_short_2(oper,a1,a2)        /* two argument short */ \
  129.     putc(oper,rle_fd), putc((char)a1,rle_fd), put16(a2)
  130.  
  131. /* long instructions */
  132. #define mk_long_1(oper,a1)        /* one argument long */ \
  133.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), put16(a1)
  134.  
  135. #define mk_long_2(oper,a1,a2)        /* two argument long */ \
  136.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), \
  137.     put16(a1), put16(a2)
  138.  
  139. /* choose between long and short format instructions */
  140. /* NOTE: these macros can only be used where a STATEMENT is legal */
  141.  
  142. #define mk_inst_1(oper,a1)        /* one argument inst */ \
  143.     if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
  144.  
  145. #define mk_inst_2(oper,a1,a2)        /* two argument inst */ \
  146.     if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
  147.  
  148. /* 
  149.  * Opcode definitions
  150.  */
  151. #define        RSkipLines(n)           mk_inst_1(RSkipLinesOp,(n))
  152.  
  153. #define        RSetColor(c)        mk_short_1(RSetColorOp,(c))
  154.                     /* has side effect of performing */
  155.                     /* "carriage return" action */
  156.  
  157. #define        RSkipPixels(n)        mk_inst_1(RSkipPixelsOp,(n))
  158.  
  159. #define        RNewLine            RSkipLines(1)
  160.  
  161. #define        RByteData(n)        mk_inst_1(RByteDataOp,n)
  162.                     /* followed by ((n+1)/2)*2 bytes */
  163.                     /* of data.  If n is odd, last */
  164.                     /* byte will be ignored */
  165.                     /* "cursor" is left at pixel */
  166.                     /* following last pixel written */
  167.  
  168. #define        RRunData(n,c)        mk_inst_2(RRunDataOp,(n),(c))
  169.                     /* next word contains color data */
  170.                     /* "cursor" is left at pixel after */
  171.                     /* end of run */
  172.  
  173. #define     REOF            mk_inst_1(REOFOp,0)
  174.                     /* Really opcode only */
  175.  
  176. extern char *vax_pshort();
  177.  
  178. /*****************************************************************
  179.  * TAG( RunSetup )
  180.  * Put out initial setup data for RLE files.
  181.  */
  182. void
  183. RunSetup(the_hdr)
  184. register rle_hdr * the_hdr;
  185. {
  186.     struct XtndRsetup setup;
  187.     register FILE * rle_fd = the_hdr->rle_file;
  188.  
  189.     put16( RLE_MAGIC );
  190.  
  191.     if ( the_hdr->background == 2 )
  192.     setup.h_flags = H_CLEARFIRST;
  193.     else if ( the_hdr->background == 0 )
  194.     setup.h_flags = H_NO_BACKGROUND;
  195.     else
  196.     setup.h_flags = 0;
  197.     if ( the_hdr->alpha )
  198.     setup.h_flags |= H_ALPHA;
  199.     if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
  200.     setup.h_flags |= H_COMMENT;
  201.  
  202.     setup.h_ncolors = the_hdr->ncolors;
  203.     setup.h_pixelbits = 8;        /* Grinnell dependent */
  204.     if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
  205.     {
  206.     fprintf( stderr,
  207.          "Color map of size %d*%d specified, but not supplied\n" );
  208.     the_hdr->ncmap = 0;
  209.     }
  210.     setup.h_cmaplen = the_hdr->cmaplen;    /* log2 of color map size */
  211.     setup.h_ncmap = the_hdr->ncmap;    /* no of color channels */
  212.     vax_pshort(setup.hc_xpos,the_hdr->xmin);
  213.     vax_pshort(setup.hc_ypos,the_hdr->ymin);
  214.     vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
  215.     vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
  216.     fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
  217.     if ( the_hdr->background != 0 )
  218.     {
  219.     register int i;
  220.     register rle_pixel *background =
  221.         (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
  222.     register int *bg_color;
  223.     /* 
  224.      * If even number of bg color bytes, put out one more to get to 
  225.      * 16 bit boundary.
  226.      */
  227.     bg_color = the_hdr->bg_color;
  228.     for ( i = 0; i < the_hdr->ncolors; i++ )
  229.         background[i] =  *bg_color++;
  230.     /* Extra byte, if written, should be 0. */
  231.     background[i] = 0;
  232.     fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
  233.     free( background );
  234.     }
  235.     else
  236.     putc( '\0', rle_fd );
  237.     if (the_hdr->ncmap > 0)
  238.     {
  239.     /* Big-endian machines are harder */
  240.     register int i, nmap = (1 << the_hdr->cmaplen) *
  241.                    the_hdr->ncmap;
  242.     register char *h_cmap = (char *)malloc( nmap * 2 );
  243.     if ( h_cmap == NULL )
  244.     {
  245.         fprintf( stderr, "Malloc failed for color map of size %d\n",
  246.              nmap );
  247.         exit( 1 );
  248.     }
  249.     for ( i = 0; i < nmap; i++ )
  250.         vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );
  251.  
  252.     fwrite( h_cmap, nmap, 2, rle_fd );
  253.     free( h_cmap );
  254.     }
  255.  
  256.     /* Now write out comments if given */
  257.     if ( setup.h_flags & H_COMMENT )
  258.     {
  259.     int comlen;
  260.     register CONST_DECL char ** com_p;
  261.  
  262.     /* Get the total length of comments */
  263.     comlen = 0;
  264.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  265.         comlen += 1 + strlen( *com_p );
  266.  
  267.     put16( comlen );
  268.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  269.         fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );
  270.  
  271.     if ( comlen & 1 )    /* if odd length, round up */
  272.         putc( '\0', rle_fd );
  273.     }
  274. }
  275.  
  276. /*****************************************************************
  277.  * TAG( RunSkipBlankLines )
  278.  * Skip one or more blank lines in the RLE file.
  279.  */
  280. void
  281. RunSkipBlankLines(nblank, the_hdr)
  282. int nblank;
  283. register rle_hdr * the_hdr;
  284. {
  285.     register FILE * rle_fd = the_hdr->rle_file;
  286.     RSkipLines(nblank);
  287. }
  288.  
  289. /*****************************************************************
  290.  * TAG( RunSetColor )
  291.  * Select a color and do carriage return.
  292.  * color: 0 = Red, 1 = Green, 2 = Blue.
  293.  */
  294. void
  295. RunSetColor(c, the_hdr)
  296. int c;
  297. register rle_hdr * the_hdr;
  298. {
  299.     register FILE * rle_fd = the_hdr->rle_file;
  300.     RSetColor(c);
  301. }
  302.  
  303. /*****************************************************************
  304.  * TAG( RunSkipPixels )
  305.  * Skip a run of background.
  306.  */
  307.  
  308. /* ARGSUSED */
  309. void
  310. RunSkipPixels(nskip, last, wasrun, the_hdr)
  311. int nskip, last, wasrun;
  312. register rle_hdr * the_hdr;
  313. {
  314.     register FILE * rle_fd = the_hdr->rle_file;
  315.     if (! last && nskip > 0)
  316.     {
  317.     RSkipPixels(nskip);
  318.     }
  319. }
  320.  
  321. /*****************************************************************
  322.  * TAG( RunNewScanLine )
  323.  * Perform a newline action.  Since CR is implied by the Set Color
  324.  * operation, only generate code if the newline flag is true.
  325.  */
  326. void
  327. RunNewScanLine(flag, the_hdr)
  328. int flag;
  329. register rle_hdr * the_hdr;
  330. {
  331.     register FILE * rle_fd = the_hdr->rle_file;
  332.     if (flag)
  333.     {
  334.     RNewLine;
  335.     }
  336. }
  337.  
  338. /*****************************************************************
  339.  * TAG( Runputdata )
  340.  * Put one or more pixels of byte data into the output file.
  341.  */
  342. void
  343. Runputdata(buf, n, the_hdr)
  344. rle_pixel * buf;
  345. int n;
  346. register rle_hdr * the_hdr;
  347. {
  348.     register FILE * rle_fd = the_hdr->rle_file;
  349.     if (n == 0)
  350.     return;
  351.  
  352.     RByteData(n-1);
  353.     fwrite((char *)buf, n, 1, rle_fd);
  354.     if ( n & 1 )
  355.     putc( 0, rle_fd );
  356. }
  357.  
  358. /*****************************************************************
  359.  * TAG( Runputrun )
  360.  * Output a single color run.
  361.  */
  362.  
  363. /* ARGSUSED */
  364. void
  365. Runputrun(color, n, last, the_hdr)
  366. int color, n, last;
  367. register rle_hdr * the_hdr;
  368. {
  369.     register FILE * rle_fd = the_hdr->rle_file;
  370.     RRunData(n-1,color);
  371. }
  372.  
  373.  
  374. /*****************************************************************
  375.  * TAG( RunputEof )
  376.  * Output an EOF opcode
  377.  */
  378. void
  379. RunputEof( the_hdr )
  380. register rle_hdr * the_hdr;
  381. {
  382.     register FILE * rle_fd = the_hdr->rle_file;
  383.     REOF;
  384. }
  385.